package cn.wolfcode.wolf2w.business.service.impl;

import cn.wolfcode.wolf2w.business.api.RemoteDestinationService;
import cn.wolfcode.wolf2w.business.api.domain.*;
import cn.wolfcode.wolf2w.business.mapper.StrategyMapper;
import cn.wolfcode.wolf2w.business.query.StrategyQuery;
import cn.wolfcode.wolf2w.business.service.*;
import cn.wolfcode.wolf2w.business.uitl.DateUtil;
import cn.wolfcode.wolf2w.business.vo.ThemeVO;
import cn.wolfcode.wolf2w.common.core.context.SecurityContextHolder;
import cn.wolfcode.wolf2w.common.redis.service.RedisService;
import cn.wolfcode.wolf2w.common.redis.util.RedisKeys;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sun.xml.internal.bind.v2.TODO;
import org.apache.commons.io.input.buffer.PeekableInputStream;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.xml.bind.ValidationEvent;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 攻略Service业务层处理
 *
 * @author ysc
 * @date 2024-12-17
 */
@Service
@Transactional
public class StrategyServiceImpl extends ServiceImpl<StrategyMapper, Strategy> implements IStrategyService {
    @Autowired
    private StrategyRankServiceImpl strategyRankService;
    @Autowired
    private IStrategyConditionService strategyConditionService;
    @Autowired
    private IStrategyThemeService strategyThemeService;
    @Autowired
    private IStrategyCatalogService strategyCatalogService;
    @Autowired
    private IStrategyContentService strategyContentService;
    @Autowired
    private RemoteDestinationService remoteDestinationService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private AmqpTemplate amqpTemplate;

    @Override
    public IPage<Strategy> queryPage(StrategyQuery qo) {
        IPage<Strategy> page = new Page<>(qo.getCurrentPage(), qo.getPageSize());

        QueryWrapper<Strategy> qw = new QueryWrapper<>();
        if (qo.getType() != null) {
            if (qo.getType() == 1 || qo.getType() == 2) {
                qw.eq("dest_id", qo.getRefid());
            } else if (qo.getType() == 3) {
                qw.eq("theme_id", qo.getRefid());
            }
        }
        return baseMapper.selectPage(page, qw);
    }


    @Override
    public List<Strategy> queryNumTop3(Long destId) {
        return lambdaQuery().eq(Strategy::getDestId, destId)
                .orderByDesc(Strategy::getViewnum)
                .last("limit 3")
                .list();

    }

    @Override
    public void statisRank() {
        //国外
        List<Strategy> abroadList = lambdaQuery().eq(Strategy::getIsabroad, 1)
                .orderByDesc(Strategy::getViewnum)
                .last("limit 10")
                .list();
        //国内
        List<Strategy> chinaList = lambdaQuery().eq(Strategy::getIsabroad, 0)
                .orderByDesc(Strategy::getViewnum)
                .last("limit 10")
                .list();
        //热门
        List<Strategy> hotList = lambdaQuery()
                .orderByDesc(Strategy::getViewnum)
                .last("limit 10")
                .list();

        Date now = new Date();
        List<StrategyRank> ranks = new ArrayList<>();

        addRank(abroadList, now, ranks, 1l);
        addRank(chinaList, now, ranks, 2l);
        addRank(hotList, now, ranks, 3l);

        strategyRankService.saveBatch(ranks);

    }

    @Override
    public List<ThemeVO> querythemeByTyp() {
        List<Strategy> strategyList = query().select("DISTINCT theme_name").list();
        List<ThemeVO> vos = new ArrayList<>();
        for (Strategy strategy : strategyList) {
            ThemeVO themeVo = new ThemeVO();
            themeVo.setThemeName(strategy.getThemeName());
            List<Strategy> sts = query().eq("theme_name", themeVo.getThemeName())
                    .select("DISTINCT dest_id,dest_name")
                    .list();
            List<Destination> dests = new ArrayList<>();
            for (Strategy st : sts) {
                Destination destination = new Destination();
                destination.setId(st.getDestId());
                destination.setName(st.getDestName());
                dests.add(destination);
            }
            themeVo.setDests(dests);
            vos.add(themeVo);
        }
        return vos;
    }


    private void addRank(List<Strategy> hotList, Date now, List<StrategyRank> ranks, long type) {
        for (Strategy strategy : hotList) {
            StrategyRank rank = new StrategyRank();
            rank.setType(type);
            rank.setStatisTime(now);
            rank.setStatisnum(strategy.getViewnum());
            rank.setDestId(strategy.getDestId());
            rank.setDestName(strategy.getDestName());
            rank.setStrategyTitle(strategy.getTitle());
            rank.setStrategyId(strategy.getId());
            ranks.add(rank);
        }
    }

    @Override
    public void statisThemeCondition() {
        //国内数据
        QueryWrapper<Strategy> queryWrapper = new QueryWrapper();
        queryWrapper.eq("isabroad", 0)
                .select("dest_id refid,dest_name name,COUNT(1) count")
                .groupBy("dest_id,dest_name");
        List<Map<String, Object>> chinaList = baseMapper.selectMaps(queryWrapper);
        //国外数据
        queryWrapper.clear();
        queryWrapper.eq("isabroad", 1)
                .select("dest_id refid,dest_name name,COUNT(1) count")
                .groupBy("dest_id,dest_name");
        List<Map<String, Object>> abroadList = baseMapper.selectMaps(queryWrapper);
        //主题数据
        queryWrapper.clear();
        queryWrapper.select("theme_id refid,theme_name name,COUNT(1) count")
                .groupBy("theme_id ,theme_name");
        List<Map<String, Object>> themeList = baseMapper.selectMaps(queryWrapper);

        Date now = new Date();
        List<StrategyCondition> conditions = new ArrayList<>();

        addCondition(abroadList, now, conditions, 1l);
        addCondition(chinaList, now, conditions, 2l);
        addCondition(themeList, now, conditions, 3l);

        strategyConditionService.saveBatch(conditions);
    }

    private void addCondition(List<Map<String, Object>> abroadList, Date now, List<StrategyCondition> conditions, Long type) {
        for (Map<String, Object> map : abroadList) {
            Long refid = (Long) map.get("refid");
            String name = (String) map.get("name");
            Long count = (Long) map.get("count");
            StrategyCondition condition = new StrategyCondition();
            condition.setRefid(refid);
            condition.setName(name);
            condition.setCount(count);
            condition.setType(type);
            condition.setStatisTime(now);
            conditions.add(condition);
        }
    }


    @Override
    public boolean mySave(Strategy strategy) {
        StrategyTheme theme = strategyThemeService.getById(strategy.getThemeId());
        strategy.setThemeName(theme.getName());
        StrategyCatalog catalog = strategyCatalogService.getById(strategy.getCatalogId());
        strategy.setCatalogName(catalog.getName());
        strategy.setDestName(catalog.getDestName());
        strategy.setDestId(catalog.getDestId());
        strategy.setCreateTime(new Date());

        List<Destination> toasts = remoteDestinationService.queryToasts(strategy.getDestId()).getData();
        if ("中国".equals(toasts.get(0).getName())) {
            strategy.setIsabroad(0l);
        } else {
            strategy.setIsabroad(1l);
        }

        strategy.setViewnum(0l);
        strategy.setReplynum(0l);
        strategy.setFavornum(0l);
        strategy.setSharenum(0l);
        strategy.setThumbsupnum(0l);

        int insert = baseMapper.insert(strategy);

        StrategyContent content = new StrategyContent();
        content.setId(strategy.getId());
        content.setContent(strategy.getContent().getContent());

        boolean flg = strategyContentService.save(content);


        String message = JSON.toJSONString(strategy);
        amqpTemplate.convertAndSend("strategyExchange", "strategyKey", message);




        return insert != 0 && flg;
    }

    @Override
    public Map<String, Object> viewnumIncrease(Long sid) {

        String key = strategyHashInit(sid);

        //阅读量加一
        redisService.incrementCacheMapValue(key, "viewnum", 1);
        //查回数据
        Map<String, Object> cacheMap = redisService.getCacheMap(key);

        return cacheMap;
    }

    @Override
    public Map<String, Object> replynumIncrease(Long sid) {
        String key = strategyHashInit(sid);

        //评论加一
        redisService.incrementCacheMapValue(key, "replynum", 1);
        //查回数据
        Map<String, Object> cacheMap = redisService.getCacheMap(key);

        return cacheMap;
    }

    private String strategyHashInit(Long sid) {
        String key = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        if (!redisService.hasKey(key)) {
            Strategy strategy = getById(sid);
            Map<String, Object> map = new HashMap<>();
            map.put("viewnum", Integer.valueOf(strategy.getViewnum().toString()));
            map.put("replynum", Integer.valueOf(strategy.getReplynum().toString()));
            map.put("favornum", Integer.valueOf(strategy.getFavornum().toString()));
            map.put("sharenum", Integer.valueOf(strategy.getSharenum().toString()));
            map.put("thumbsupnum", Integer.valueOf(strategy.getThumbsupnum().toString()));
            map.put("id", sid);
            redisService.setCacheMap(key, map);
        }
        return key;
    }

    @Override
    public Map<String, Object> favor(Long sid) {
        Long uid = SecurityContextHolder.getUserId();
        String key = RedisKeys.STRATEGY_FAVOR.join(uid.toString());
        if (!redisService.hasKey(key)) {
            Set<Long> sids = new HashSet<>();
            sids.add(-1l);
            redisService.setCacheSet(key, sids);
        }
        String hashKey = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        boolean flg = false;
        if (redisService.isCacheSetContains(key, sid)) {
            //取消收藏
            redisService.incrementCacheMapValue(hashKey, "favornum", -1);
            redisService.deleteCacheSetValue(key, sid);
        } else {
            //收藏
            redisService.incrementCacheMapValue(hashKey, "favornum", 1);
            redisService.addCacheSetValue(key, sid);
            flg = true;
        }
        Map<String, Object> cacheMap = redisService.getCacheMap(hashKey);
        cacheMap.put("result", flg);
        return cacheMap;
    }

    @Override
    public boolean isUserFavor(Long uid, Long sid) {
        String key = RedisKeys.STRATEGY_FAVOR.join(uid.toString());

        return redisService.isCacheSetContains(key, sid);
    }

    //将 Redis 中的临时统计数据持久化到数据库中，确保数据库和缓存数据一致性。
    @Override
    public void statisHashPersistence() {
        String statisKey = RedisKeys.STRATEGY_STATIS_HASH.join("*"); //strategy_statis_hash:*
        Collection<String> keys = redisService.keys(statisKey); //keys strategy_statis_hash:*
        if (keys != null && keys.size() > 0) {
            for (String key : keys) {
                Map<String, Object> map = redisService.getCacheMap(key);
                lambdaUpdate().eq(Strategy::getId, map.get("id"))
                        .set(Strategy::getViewnum, map.get("viewnum"))
                        .set(Strategy::getReplynum, map.get("replynum"))
                        .set(Strategy::getFavornum, map.get("favornum"))
                        .set(Strategy::getSharenum, map.get("sharenum"))
                        .set(Strategy::getThumbsupnum, map.get("thumbsupnum"))
                        .update();

            }
        }
    }


    @Override
    public Map<String, Object> thumbsup(Long sid) {
        Long uid = SecurityContextHolder.getUserId();
        String key = RedisKeys.STRATEGY_THUMBSUP.join(sid.toString(), uid.toString());
        if (!redisService.hasKey(key)) {
            Date now = new Date();
            Date end = DateUtil.getEndDate(now);
            long time = DateUtil.getDateBetween(now, end);
            time = time == 0 ? 1 : time;

            redisService.setCacheObject(key, 0, time, TimeUnit.SECONDS);
        }
        Long ret = redisService.incrementCacheObjectValue(key, 1);
        //统计数字的key
        String hashKey = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        if (ret > 5) {
            //今天已经点赞过5次
            Map<String, Object> cacheMap = redisService.getCacheMap(hashKey);
            cacheMap.put("result", false);
            return cacheMap;
        } else {
            redisService.incrementCacheMapValue(hashKey, "thumbsupnum", 1);
            Map<String, Object> cacheMap = redisService.getCacheMap(hashKey);
            cacheMap.put("result", true);
            return cacheMap;
        }
    }

//    @Override
//    public void esDateInit() {
//        // TODO: 2024/12/26m 查询mysql内容 存储到es中
//
//    }


}